package com.im323.common.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HttpClientUtils {

	private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);

	private static final String userAgent = "imDnsPodClientForJava/0.1(wangpu2116@sina.com)";

	/**
	 * 发送表单请求<br />
	 * 默认UTF-8编码
	 * 
	 * @author 王璞
	 * @date 2016年11月14日 上午10:34:26
	 * @param url
	 *            请求地址
	 * @return
	 */
	public static String doPost(String url) {
		return doPost(url, null, null, Consts.UTF_8);
	}

	public static String doGet(String url) {
		return doGet(url, null, null, Consts.UTF_8);
	}

	/**
	 * 发送表单请求<br />
	 * 默认UTF-8编码
	 * 
	 * @author 王璞
	 * @date 2016年11月14日 上午10:34:26
	 * @param url
	 *            请求地址
	 * @param params
	 *            参数
	 * @return
	 */
	public static String doPost(String url, Map<String, String> params) {
		return doPost(url, params, null, Consts.UTF_8);
	}

	public static String doGet(String url, Map<String, String> params) {
		return doGet(url, params, null, Consts.UTF_8);
	}

	/**
	 * 发送表单请求<br />
	 * 默认UTF-8编码
	 * 
	 * @author 王璞
	 * @date 2016年11月14日 上午10:34:26
	 * @param url
	 *            请求地址
	 * @param params
	 *            参数
	 * @param header
	 *            HTTP表头
	 * @return
	 */
	public static String doPost(String url, Map<String, String> params, Map<String, String> header) {
		return doPost(url, params, header, Consts.UTF_8);
	}

	public static String doGet(String url, Map<String, String> params, Map<String, String> header) {
		return doGet(url, params, header, Consts.UTF_8);
	}

	/**
	 * 发送表单请求
	 * 
	 * @author 王璞
	 * @date 2016年11月14日 上午10:33:56
	 * @param url
	 *            请求地址
	 * @param params
	 *            参数
	 * @param header
	 *            HTTP表头
	 * @param charset
	 *            编码
	 * @return
	 */
	public static String doPost(String url, Map<String, String> params, Map<String, String> header, Charset charset) {
		String result = "";

		HttpClient httpClient = getHttpClient();
		HttpPost httpPost = getHttpPost(url);
		if (header != null && header.size() > 0) {
			setHeader(header, httpPost);
		}

		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		if (params != null) {
			Set<String> keySet = params.keySet();
			for (String key : keySet) {
				nvps.add(new BasicNameValuePair(key, params.get(key)));
			}
		}
		try {
			httpPost.setEntity(new UrlEncodedFormEntity(nvps, charset));
			HttpResponse response = httpClient.execute(httpPost);
			result = EntityUtils.toString(response.getEntity(), charset);
		} catch (ParseException | IOException pe) {
			logger.error("doPost url=" + url, pe);
		}
		logger.debug("doPost url={}\r\n{}", url, result);
		return result;
	}

	public static String doGet(String url, Map<String, String> params, Map<String, String> header, Charset charset) {
		String paramUrl = url;
		String result = "";

		HttpClient httpClient = getHttpClient();

		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		if (params != null) {
			Set<String> keySet = params.keySet();
			for (String key : keySet) {
				nvps.add(new BasicNameValuePair(key, params.get(key)));
			}
			try {
				String string = IOUtils.toString(new UrlEncodedFormEntity(nvps, charset).getContent(), charset);
				paramUrl = paramUrl + "?" + string;
			} catch (IOException e) {
				logger.error("doGet url=" + url, e);
			}
		}

		HttpGet httpGet = getHttpGet(paramUrl);
		if (header != null && header.size() > 0) {
			setHeader(header, httpGet);
		}
		try {
			HttpResponse response = httpClient.execute(httpGet);
			result = EntityUtils.toString(response.getEntity(), charset);
		} catch (ParseException | IOException e) {
			logger.error("doGet url=" + url, e);
		}
		logger.debug("doGet url={}\r\n{}", url, result);
		return result;
	}

	/**
	 * 发送json请求
	 * 
	 * @author 王璞
	 * @date 2016年11月14日 上午10:36:56
	 * @param url
	 *            请求地址
	 * @param jsonObject
	 *            json对象
	 * @param clazz
	 * @return T
	 */
	public static <T> T doJson(String url, Object jsonObject, Class<T> clazz) {
		String result = doJson(url, JsonUtil.toJson(jsonObject), null, Consts.UTF_8);
		return JsonUtil.toObj(result, clazz);
	}

	/**
	 * 发送json请求
	 * 
	 * @author 王璞
	 * @date 2016年11月14日 上午10:13:39
	 * @param url
	 *            请求地址
	 * @param jsonObject
	 *            json对象
	 * @return
	 */
	public static String doJson(String url, Object jsonObject) {
		return doJson(url, JsonUtil.toJson(jsonObject), null, Consts.UTF_8);
	}

	/**
	 * 发送json请求
	 * 
	 * @author 王璞
	 * @date 2016年11月14日 上午10:14:04
	 * @param url
	 *            请求地址
	 * @param jsonContent
	 *            json字符串内容
	 * @return
	 */
	public static String doJson(String url, String jsonContent) {
		return doJson(url, jsonContent, null, Consts.UTF_8);
	}

	/**
	 * 发送json请求
	 * 
	 * @author 王璞
	 * @date 2016年11月14日 上午10:11:09
	 * @param url
	 * @param jsonContent
	 *            json内容
	 * @param header
	 *            HTTP头部
	 * @param charset
	 *            编码
	 * @return
	 */
	public static String doJson(String url, String jsonContent, Map<String, String> header, Charset charset) {
		String result = "";

		HttpClient httpClient = getHttpClient();
		HttpPost httpPost = getHttpPost(url);
		setHeader(header, httpPost);

		StringEntity entity = new StringEntity(jsonContent, charset);
		entity.setContentType("application/json");

		try {
			httpPost.setEntity(entity);
			HttpResponse httpResponse = httpClient.execute(httpPost);
			result = EntityUtils.toString(httpResponse.getEntity(), charset);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
		}
		return result;
	}

	/**
	 * 下载文件
	 * 
	 * @author 王璞
	 * @date 2016年11月14日 上午9:58:56
	 * @param url
	 *            下载地址
	 * @param desFilePath
	 *            文件存放路径
	 * @return File
	 */
	public static HttpResponse downloadFile(String url, String desFilePath, Map<String, String> params) {
		return downloadFile(url, new File(desFilePath), params);
	}

	/**
	 * 下载文件
	 * 
	 * @author 王璞
	 * @date 2016年11月14日 上午9:58:06
	 * @param url
	 *            下载地址
	 * @param file
	 *            存储文件
	 * @return File
	 */
	public static HttpResponse downloadFile(String url, File file, Map<String, String> params) {
		HttpClient httpClient = getHttpClient();
		HttpPost httpPost = getHttpPost(url);

		HttpResponse httpResponse = null;
		BufferedInputStream bufferedInputStream = null;
		BufferedOutputStream bufferedOutputStream = null;
		try {
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
			if (params != null) {
				Set<String> keySet = params.keySet();
				for (String key : keySet) {
					nvps.add(new BasicNameValuePair(key, params.get(key)));
				}
			}
			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
			httpResponse = httpClient.execute(httpPost);

			InputStream inputStream = httpResponse.getEntity().getContent();
			bufferedInputStream = new BufferedInputStream(inputStream);
			bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
			byte[] buff = new byte[1024 * 1024];
			int length = 0;
			while ((length = bufferedInputStream.read(buff)) != -1) {
				bufferedOutputStream.write(buff, 0, length);
				bufferedOutputStream.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (bufferedInputStream != null) {
				try {
					bufferedInputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (bufferedOutputStream != null) {
				try {
					bufferedOutputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return httpResponse;
	}

	private static HttpClient getHttpClient() {
		HttpClientBuilder builder = HttpClientBuilder.create();
		// HttpHost proxy = new HttpHost("192.168.1.100", 1080);
		// builder.setProxy(proxy);
		return builder.build();
	}

	private static HttpPost getHttpPost(String url) {
		HttpPost post = new HttpPost(url);
		post.setHeader("User-Agent", userAgent);
		return post;
	}

	private static HttpGet getHttpGet(String url) {
		HttpGet httpGet = new HttpGet(url);
		httpGet.setHeader("User-Agent", userAgent);
		return httpGet;
	}

	private static void setHeader(Map<String, String> header, Object obj) {
		if (header != null) {// 设置header
			Set<String> headerKey = header.keySet();
			for (Iterator<String> iterator = headerKey.iterator(); iterator.hasNext();) {
				String key = iterator.next();
				String value = header.get(key);
				if (obj instanceof HttpPost) {
					((HttpPost) obj).setHeader(key, value);
				}
				if (obj instanceof HttpGet) {
					((HttpPost) obj).setHeader(key, value);
				}
			}
		}
	}
}